package com.jagochan.imchat.module.common.interceptor;

import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Charsets;
import com.jagochan.imchat.module.common.domain.vo.resp.ApiResult;
import com.jagochan.imchat.module.user.service.LoginService;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * 获取请求头的token字符串，判断是否有效？
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
    private static final String TOKEN_HEADER_KEY = "Authorization";
    private static final String TOKEN_PREFIX = "Bearer ";
    public static final String UID_KEY = "uid";

    @Resource
    private LoginService loginService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = getTokenHeader(request);
        // 判断token是否有效
        Long uid = loginService.getValidUid(token);
        if (Objects.nonNull(uid)) { // token有效
            request.setAttribute(UID_KEY, uid);
        } else {
            if (checkWhiteList(request)) { // 白名单请求
                return true;
            } else {
                response.setStatus(401);
                response.setContentType(ContentType.JSON.toString(Charsets.UTF_8));
                response.getWriter().write(JSONUtil.toJsonStr(ApiResult.fail(401, "token已过期")));
                return false;
            }

        }
        return true;
    }

    private boolean checkWhiteList(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String regex = "^/[a-zA-Z0-9]+/[a-zA-Z0-9]+/public/.*$";
        Pattern pattern = Pattern.compile(regex);
        return pattern.matcher(requestURI).matches();
    }

    /**
     * 从HTTP请求头中提取token字符串
     *
     * @param request HTTP请求对象
     * @return 提取的token值字符串（不含前缀），若不存在则返回null
     */
    private String getTokenHeader(HttpServletRequest request) {
        // 获取请求头中指定键对应的字段值
        String token = request.getHeader(TOKEN_HEADER_KEY);

        // 使用Optional链式处理：过滤、截取并返回结果
        return Optional.ofNullable(token)
                .filter(s -> s.startsWith(TOKEN_PREFIX)) // 过滤掉不以前缀开头的值
                .map(s -> s.substring(TOKEN_PREFIX.length())) // 截取前缀后的部分
                .orElse(null); // 若无符合条件的值则返回null
    }
}
